﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint;
using System.Xml.Serialization;
using MissingUserPermission_2007.Entities;

namespace MissingUserPermission_2007
{
   
        class Program
        {

            public static Permissions PermissionMask = new Permissions();

            // public static bool ConvertClaims;

            static void Main(string[] args)
            {
                try
                {

                    Console.WriteLine("Identify missing User Permissions on Claims Conversion (developed by: daenet GmbH (Nadine Storandt))");
                    Console.WriteLine("----------------------------------------------------------");
                    Console.WriteLine("This tool gives the administrator the ability to check for any missing user permission after claims migration. ");

                    Console.WriteLine("Following Options are available:");

                    Console.WriteLine("1. Document User Permissions before Claims Migration");
                    
                    var option = Console.ReadLine();

                    switch (option)
                    {
                        case "1":
                            documentUserPermissionsBeforeClaims();
                            break;
                        
                        default:
                            throw new Exception("Not supported Option, please restart.");
                    }

                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    Console.ReadLine();
                }

            }


            private static void documentUserPermissionsBeforeClaims()
            {
                try
                {
                    Console.WriteLine("Following Options are available:");

                    Console.WriteLine("1. Document whole Farm");
                    Console.WriteLine("2. Document WebApplication");
                    Console.WriteLine("3. Document SiteCollections within specified Database");
                    Console.WriteLine("4. Document specific SiteCollection");

                    var option = Console.ReadLine();

                    switch (option)
                    {
                        case "1":
                            documentWholeFarm();
                            break;
                        case "2":
                            Console.WriteLine("Please enter the Url for the webApp which should be documented:");

                            var webApp = Console.ReadLine();

                            if (String.IsNullOrEmpty(webApp))
                                throw new Exception("Please restart, no webApp url enterd.");

                            documentWebApplication(webApp);

                            break;
                        case "3":
                            Console.WriteLine("Please enter the name of the database which should be documented:");

                            var db = Console.ReadLine();

                            if (String.IsNullOrEmpty(db))
                                throw new Exception("Please restart, no db name enterd.");

                            documentDatabase(db);
                            break;
                        case "4":
                            Console.WriteLine("Please enter the Url for the sitecollection which should be documented:");

                            var siteCollection = Console.ReadLine();
                            documentSiteCollection(siteCollection);

                            break;
                        default:
                            throw new Exception("Not supported Option, please restart.");
                    }

                    serializeResults("PermissionBeforeClaims.xml");


                    Console.WriteLine("Execution done! Press any key to exit ... ");
                    Console.ReadLine();

                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }

            private static void documentSiteCollection(string siteCollection)
            {
                try
                {

                    if (!String.IsNullOrEmpty(siteCollection))
                    {
                        SPSecurity.RunWithElevatedPrivileges(delegate()
                        {
                            using (SPSite site = new SPSite(siteCollection))
                            {

                                if (site == null)
                                    throw new Exception("Site can not be found. Please ensure this site exists");


                                if (PermissionMask.sites == null)
                                    PermissionMask.sites = new List<Site>();

                                recursive(site.RootWeb);
                            }
                        });
                    }
                    else
                        throw new Exception("no siteCollection url entered. Please restart.");

                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }

            private static void recursive(SPWeb web)
            {
                var curSite = new Site();

                curSite.SiteId = web.ID;
                curSite.Url = web.Url;

                curSite.Groups = getAllGroupsWithUsersFromWeb(web);

                PermissionMask.sites.Add(curSite);

                if (web.Webs.Count > 0)
                {
                    foreach (SPWeb oweb in web.Webs)
                    {
                        recursive(oweb);
                    }
                }

                if (web != null)
                    web.Dispose();
            }


            /// <summary>
            /// Serialize the results of type Permission to a xml file
            /// </summary>
            /// <param name="fileName"></param>
            private static void serializeResults(string fileName)
            {
                using (var writer = new System.IO.StreamWriter(fileName, false))
                {
                    var serializer = new XmlSerializer(PermissionMask.GetType());
                    serializer.Serialize(writer, PermissionMask);
                    writer.Flush();
                }

            }

            /// <summary>
            /// Deserialize the results of type Permission from file to object
            /// </summary>
            /// <param name="fileName"></param>
            /// <returns></returns>
            private static Permissions deserializeResult(string fileName)
            {
                Permissions result = new Permissions();
                using (var reader = new System.IO.StreamReader(fileName))
                {
                    var serializer = new XmlSerializer(PermissionMask.GetType());
                    result = (Permissions)serializer.Deserialize(reader);

                }

                return result;
            }



            /// <summary>
            /// documents all groups with Usersnames
            /// </summary>
            /// <param name="web"></param>
            /// <returns></returns>
            private static List<Group> getAllGroupsWithUsersFromWeb(SPWeb web)
            {
                List<Group> result = new List<Group>();


                foreach (SPGroup group in web.Groups)
                {
                    Group curGroup = new Group();

                    curGroup.Name = group.Name;
                    curGroup.UserNames = new List<string>();

                    foreach (SPUser user in group.Users)
                    {
                        
                            curGroup.UserNames.Add(user.LoginName);
                    }

                    result.Add(curGroup);
                }

                return result;
            }

            private static void documentDatabase(string dbName)
            {
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    SPWebServiceCollection webServices = new SPWebServiceCollection(SPFarm.Local);
                    foreach (SPWebService webService in webServices)
                    {
                        foreach (SPWebApplication wa in webService.WebApplications)
                        {
                            foreach (SPContentDatabase db in wa.ContentDatabases)
                            {

                                if (db.Name == dbName)
                                {
                                    foreach (SPSite site in db.Sites)
                                    {
                                        documentSiteCollection(site.Url);
                                    }
                                }
                            }

                        }
                    }
                });
            }

            private static void documentWebApplication(string webAppUrl)
            {
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    SPWebApplication webApp = SPWebApplication.Lookup(new Uri(webAppUrl));

                    foreach (SPSite site in webApp.Sites)
                    {
                        documentSiteCollection(site.Url);
                    }
                });
            }

            private static void documentWholeFarm()
            {
                SPSecurity.RunWithElevatedPrivileges(delegate()
                {
                    SPWebServiceCollection webServices = new SPWebServiceCollection(SPFarm.Local);
                    foreach (SPWebService webService in webServices)
                    {
                        foreach (SPWebApplication wa in webService.WebApplications)
                        {
                            documentWebApplication(wa.GetResponseUri(SPUrlZone.Default).AbsoluteUri);
                        }
                    }
                });
            }
        }
  
}
